#ifndef ROCKSDB_BASIC_OPERATOR_UNITEST_H_
#define ROCKSDB_BASIC_OPERATOR_UNITEST_H_

#include <regex>
#include "unitest_comm.h"
#include "../include/rocksdb_adapter/rocksdb_basic_operator.h"
#include "../include/config_parser/config_manager.h"
#include "../include/vet_cmd_handler.h"

UNITEST_NAMESPACE_BEGIN
class RocksDbTest : public testing::Test{
protected:
    virtual void SetUp() {
        vectorindex::ConfigManager::Instance()->InitConfig();

        const vectorindex::VectorIndexContext* p_vet_cnt = 
                    vectorindex::ConfigManager::Instance()->GetVectorIndexTable();

        stat_init_log_(p_vet_cnt->s_service_name_.c_str(),
                p_vet_cnt->s_log_dir_.c_str());
        stat_set_log_level_(p_vet_cnt->ui_log_level_);

        bool b_ret = vectorindex::RocksDbOperator::Instance()->InitRocksDb(p_vet_cnt->s_rocksdb_dir_);
        EXPECT_TRUE(b_ret);
    }

    bool ParseVetKey(std::string s_key ,
             UniqueIndexFlag& o_uniq_index,
             std::vector<float>& o_vector_data)
    {
        std::size_t i_fir_pos = s_key.find_first_of("#");
        if (i_fir_pos != std::string::npos) {
            o_uniq_index.i_appid_ = atoi(s_key.substr(0,i_fir_pos).c_str());
        }
    
        std::size_t i_sec_pos = s_key.find_last_of("#");
        if (i_sec_pos != std::string::npos) {
            o_uniq_index.i_field_id_ = atoi(s_key.substr(i_fir_pos + 1 , i_sec_pos - i_fir_pos - 1).c_str());
        }

        if (-1 == o_uniq_index.i_appid_ || -1 == o_uniq_index.i_field_id_) {
            log_error("rocksdb has illegel key");
            return false;
        }
    
        s_key = s_key.substr(i_sec_pos + 1);
        const char* split_flag = "|";
        char* p = strtok((char*)s_key.c_str() , split_flag);
        while (p != NULL) {
            o_vector_data.emplace_back(atof(p));
            p = strtok(NULL , split_flag);
        }

        return true;
    };
};

TEST_F(RocksDbTest , Rocksdb_IRUS_Test){
    std::string s_test_key_1 = "10008#14#10.00300|100.00400|";

    UniqueIndexFlag o_uniq_index;
    std::vector<float> o_vector_data;

    bool b_ret = ParseVetKey(s_test_key_1 , o_uniq_index , o_vector_data);
    EXPECT_TRUE(b_ret);

    EXPECT_TRUE(o_uniq_index.i_appid_ == 10008);
    EXPECT_TRUE(o_uniq_index.i_field_id_ == 14);

    EXPECT_TRUE(o_vector_data.size() == 2);
    std::cout<< o_vector_data[0] <<std::endl;
    std::cout<< o_vector_data[1] <<std::endl;
    EXPECT_TRUE(abs(o_vector_data[0] - 10.00300) < 0.0001);
    EXPECT_TRUE(abs(o_vector_data[1] - 100.00400) < 0.0001);

    std::string s_test_key_2 = "10008#14#100.00300|10.00400|";
    std::string s_test_value_01 = "12345";
    std::string s_update_value = "6789";

    vectorindex::RocksDbOperator* p_rocksdb_opera = vectorindex::RocksDbOperator::Instance();

    int i_ret = p_rocksdb_opera->InsertEntry(s_test_key_1 , s_test_value_01);
    EXPECT_TRUE(0 == i_ret);

    // test insert api
    i_ret = p_rocksdb_opera->InsertEntry(s_test_key_1 , s_test_value_01);
    EXPECT_TRUE(-1 == i_ret);

    std::string s_get_value;
    i_ret = p_rocksdb_opera->GetEntry(s_test_key_1 , s_get_value);
    EXPECT_TRUE(0 == i_ret);
    EXPECT_TRUE(s_test_value_01 == s_get_value);

    // test delete api
    i_ret = p_rocksdb_opera->DeleteEntry(s_test_key_1);
    EXPECT_TRUE(0 == i_ret);
    i_ret = p_rocksdb_opera->GetEntry(s_test_key_1 , s_get_value);
    EXPECT_TRUE(-1 == i_ret);

    // test update api
    i_ret = p_rocksdb_opera->UpdateEntry(s_test_key_1 , s_update_value);
    EXPECT_TRUE(-1 == i_ret);// key no found

    i_ret = p_rocksdb_opera->InsertEntry(s_test_key_1 , s_test_value_01);
    EXPECT_TRUE(0 == i_ret);// insert s_test_value_01 value

    i_ret = p_rocksdb_opera->UpdateEntry(s_test_key_1 , s_update_value);
    EXPECT_TRUE(0 == i_ret);// update s_test_value_01 2 s_update_value

    i_ret = p_rocksdb_opera->GetEntry(s_test_key_1 , s_get_value);
    EXPECT_TRUE(s_update_value == s_get_value);

    // test batch update api
    vectorindex::RocksDbOperator::UpdatePair o_update_pair;
    o_update_pair.emplace_back(std::make_pair(s_test_key_1 , "4410"));
    o_update_pair.emplace_back(std::make_pair(s_test_key_2 , "1104"));

    std::set<std::string> o_del_set;
    i_ret = p_rocksdb_opera->BatchUpdate(o_del_set , o_update_pair);
    EXPECT_TRUE(0 == i_ret);
    std::vector<int> o_col_fam_type_vet(2, vectorindex::E_COL_FAM_VECTOR_DATA);

    // test get iterator api
    rocksdb::Iterator* iter = p_rocksdb_opera->GetIterator(vectorindex::E_COL_FAM_VECTOR_DATA);
    for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
        EXPECT_TRUE((iter->key().ToString() == s_test_key_1) 
            || (iter->key().ToString() == s_test_key_2));
        EXPECT_TRUE((iter->value().ToString() == "4410") 
            || (iter->value().ToString() == "1104"));
    }
    
    // test muti get api
    std::vector<std::string> o_multi_key;
    o_multi_key.emplace_back(s_test_key_1);
    o_multi_key.emplace_back(s_test_key_2);

    std::vector<std::string> o_multi_values;
    std::set<int> error_seq_id;
    std::set<int> no_found_seq_id;
    b_ret = p_rocksdb_opera->MultiGetEntry(
                        o_col_fam_type_vet,
                        o_multi_key,
                        o_multi_values,
                        error_seq_id,
                        no_found_seq_id);
    EXPECT_TRUE("4410" == o_multi_values[0]);
    EXPECT_TRUE("1104" == o_multi_values[1]);
    EXPECT_TRUE(b_ret);

    // test batch delete api
    std::set<std::string> o_delete_set;
    o_delete_set.insert(s_test_key_1);
    o_delete_set.insert(s_test_key_2);

    std::string s_no_exist_key = "10008#14#1000.00300|1000.00400|";
    i_ret = p_rocksdb_opera->GetEntry(s_no_exist_key , s_get_value);
    EXPECT_TRUE(-1 == i_ret);

    o_delete_set.insert(s_no_exist_key);

    i_ret = p_rocksdb_opera->BatchUpdate(o_delete_set);
    std::cout<< "delete state:" << i_ret <<std::endl;
    EXPECT_TRUE(0 == i_ret);
};

UNITEST_NAMESPACE_END
#endif